<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  <link rel="shortcut icon" href="../img/favicon.ico" type="image/x-icon">
  <link rel="stylesheet" href="../css/style.css">
  <title>实例方法与全局api的实现</title>
</head>

<body>
  <h2>实例方法与全局api的实现</h2>
  <h3>new Vue()</h3>
  <li>initMixin(): 挂载_init方法供构造函数调用</li>
  <li>stateMixin(): 挂载$watch, $set, $delete</li>
  <li>eventMixin(): 在原型上挂载$on, $off, $once, $emit</li>
  <li>lifecycleMixin(): _update $forceUpdate $destroy $off</li>
  <li>renderMinxin(): $nextTick _render</li>

  <h3>数据相关</h3>
  <li>
    《与变化侦测相关API》中已经介绍过。不再赘述
  </li>

  <h3>事件相关的方法</h3>
  <pre>
      class VueTest {
        constructor () {
          this._event = {}
        }
        $on (event, callback) {
          (this._event[event] = []).push(callback)
          return this
        }
        $off (event) {
          this._event[event] = []
          return this
        }
        $once (event, callback) {
          const on = () => {
            this.$off(event)
            callback.apply(this, arguments)
          }
          this.$on(event, on)
          return this
        }
        $emit (event) {
          for (let v of this._event[event].values()) {
            v(arguments)
          }
        }
      }
      const v = new VueTest()
      v.$on('lee', () => {
        console.log('i am a lee')
      })
      v.$emit('lee') // i am a lee
      v.$off('lee')
      // v.$emit('lee') 报错
      v.$once('lee2', () => {
        console.log('i am a lee2')
      })
      v.$emit('lee2') // i am a lee2
      v.$emit('lee2') // 没打印
  </pre>

  <h3>生命周期相关的实例方法</h3>
  <li>
    vm.$forceUpdate()。是迫使Vue.Js实例重新渲染。它仅仅影响实例本身以及插入插槽内容的子组件。每一个实例都有一个watcher,$forceUpdate方法的实现原理是手动调用watcher的update方法。
  </li>
  <li>
    vm.$destory()。作用是完全销毁一个实例，它会清理实例与其他实例的链接，清除监听器等。同时会触发beforeDestroy,destoryed()的钩子函数
  </li>
  <li>
    vm.$nextTick():作用是将回调延迟到下次DOM更新周期之后执行。它与全局方法Vue.nextTick一样
  </li>
  <li>
    vm.$mount(): 会自动把Vue.js实例挂载到DOM元素。想让Vue.js实例具有关联的DOM元素，只有使用vm.$mount一种途径
  </li>
  <li>
    <pre>
      const mount = Vue.prototype.$mount
      Vue.prototype.$mounted = function (el) { 
        return mount.call(this, el)
      }
    </pre>
  </li>
  <h3>事件循环</h3>
  <li>
    代码在处理异步任务时，主线程会挂起这个任务。当任务处理完后，JS会将这个事件加入一个队列中，我们称这个队列为<span>事件队列</span>。被放入事件队列中的事件不会立刻执行其回调，而是等待当前主线程中的所有任务执行任务都执行完毕后，会去查找事件队列中是否有任务。
  </li>
  <li>
    异步任务分两种类型：微任务和宏任务。不同类型的任务会被分配到不同的事件队列
  </li>
  <li>
    当执行栈中的所有任务都被执行完后，会去检查微任务队列中是否有事件的存在，如果存在，则会依次执行微任务队列中事件对应的回调，直到为空。然后去宏任务队列中取出一个事件，把对应的回调加入执行栈。当执行栈中所有任务执行完毕后，检查微任务队列中是否有事件存在。无限循环往复，就叫做事件循环
  </li>
  <li>
    微任务： Promise.then(), MutationObserver, promise.nextTick
  </li>
  <li>
    宏任务： setTimieout,setInterval,UI交互事件（touch, click等）
  </li>
  <h4>全局API的实现原理</h4>
  <li>
    Vue.extend的作用是创建一个子类，所以可以创建一个子类，然后让继承Vue身上的一些功能。接受的参数是组件参数。<span>内部实现原理是调用了this.init()初始化了一个组件</span>
  </li>
  <li>
    Vue.nextTick()：在下次DOM更新循环结束之后执行延迟回调。修改数据之后立即使用这个方法获取更新后的DOM
  </li>
  <li>
    Vue.set(): 设置对象的属性。如果对象是响应式的，确保属性被创建后也是响应式的。同时触发视图更新
  </li>
  <li>
    Vue.delete(): 删除对象的属性。如果对象是相应式的，确保删除能触发更新视图。
  </li>
  <li>
    <span>Vue.directive()</span>: 
    <pre>
      // 注册
      Vue.directive('my-directive', {
        bind() {},
        inserted() {},
        update() {},
        componentUpdated() {},
        unbind() {}
      })

      // 注册 （指令函数）
      Vue.directive('my-directive', function () {
        // 这里将会被bind和update调用
      })

      // getter 方法，返回已注册的指令
      var myDirective = Vue.directive('my-directive')
    </pre>
  </li>
  <li>
    <span>Vue.filter(id, [defintion])</span>
    <pre>
      // 注册
      Vue.filter('my-filter', function (value) {
        // 返回处理后的值
      })
      // getter方法，返回已注册的过滤器
      var myFilter = Vue.filter('my-filter')
    </pre>
  </li>
  <li>
    <span>Vue.component(): 注册或者获取全局组件</span>:
    <pre>
      // 注册组件，传入一个扩展过的构造器
      Vue.component('my-component', Vue.extend({...}))
      // 注册组件，传入一个选象对象（自动调用Vue.extend）
      Vue.component({...})
      // 获取注册的组件(始终返回的构造器)
      var MyComponent = Vue.component('my-component')
    </pre> 
  </li>
  <li>
    Vue.use: 用法<span>安装Vue.js插件</span>，如果插件是一个对象，必须提供<span>install</span>方法。如果插件是一个函数，它会被作为install方法。调用install方法时，会将Vue作为参数传入。install方法被同一个插件多次调用时，插件也只会被安装一次
  </li>
  <li>
    Vue.minxin: 全局注册一个混入，影响注册之后创建的每个Vue.js实例。插件作者可以使用混入向组件注入自定义行为。
  </li>
  <li>
    Vue.compile(): 编译模板字符串并返回包含渲染函数的对象。只在完整版中才有效。
  </li>
  <li>
    
  </li>


  <script src="../js/constructor/13.js"></script>
</body>

</html>